/**
 * Copyright (c) 2016-2023, Michael Yang 杨福海 (fuhai999@gmail.com).
 * <p>
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.jpress.web.commons.controller;

import com.jfinal.aop.Inject;
import com.jfinal.core.JFinal;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.Ret;
import com.jfinal.upload.UploadFile;
import io.jboot.utils.FileUtil;
import io.jboot.utils.StrUtil;
import io.jboot.web.attachment.AttachmentManager;
import io.jboot.web.controller.annotation.RequestMapping;
import io.jboot.web.validate.EmptyValidate;
import io.jboot.web.validate.Form;
import io.jpress.JPressConfig;
import io.jpress.JPressOptions;
import io.jpress.commons.utils.AliyunOssUtils;
import io.jpress.commons.utils.AttachmentUtils;
import io.jpress.commons.utils.ImageUtils;
import io.jpress.model.Attachment;
import io.jpress.model.User;
import io.jpress.service.AttachmentCategoryService;
import io.jpress.service.AttachmentService;
import io.jpress.web.base.UserControllerBase;
import io.jpress.web.functions.PermissionFunctions;

import java.io.File;
import java.util.Set;

/**
 * @author Michael Yang 杨福海 （fuhai999@gmail.com）
 * @version V1.0
 * @Title: 首页
 * @Package io.jpress.web.admin
 */
@RequestMapping("/commons/attachment")
public class AttachmentController extends UserControllerBase {


    @Inject
    private AttachmentService service;

    @Inject
    private AttachmentCategoryService categoryService;

    public void upload() {
        if (!isMultipartRequest()) {
            renderError(404);
            return;
        }

        UploadFile uploadFile = getFile();
        if (uploadFile == null) {
            renderJson(Ret.fail().set("message", "请选择要上传的文件"));
            return;
        }

        User loginedUser = getLoginedUser();


        File file = uploadFile.getFile();
        if (loginedUser == null || !loginedUser.isStatusOk()) {
            if (!file.delete()) {
                LogKit.warn("file can not delete: {}", file.getAbsolutePath());
            }
            renderJson(Ret.of("error", Ret.of("message", "当前用户未激活，不允许上传任何文件。")));
            return;
        }


        //没有拥有： "运行上传任意类型文件" 的权限
        if (!PermissionFunctions.hasPermission("attachment_upload_any_suffix")) {

            //配置了禁止的文件权限
            String allowSuffix = JPressOptions.get("attachment_allow_suffix");
            if (StrUtil.isNotBlank(allowSuffix)) {
                Set<String> allowSuffixes = StrUtil.splitToSetByComma(allowSuffix);
                int lastIndexOf = uploadFile.getFileName().lastIndexOf(".");
                if (lastIndexOf <= 0) {
                    if (!file.delete()) {
                        LogKit.warn("file can not delete: {}", file.getAbsolutePath());
                    }
                    renderJson(Ret.fail().set("message", "不支持此类文件上传"));
                    return;
                }
                String suffix = uploadFile.getFileName().substring(lastIndexOf + 1).toLowerCase();
                boolean allow = false;
                for (String allowSffix : allowSuffixes) {
                    if (suffix.equalsIgnoreCase(allowSffix.toLowerCase())) {
                        allow = true;
                        break;
                    }
                }

                if (!allow) {
                    if (!file.delete()) {
                        LogKit.warn("file can not delete: {}", file.getAbsolutePath());
                    }
                    renderJson(Ret.fail().set("message", "不支持此类文件上传"));
                    return;
                }
            }
            //不配置，默认的文件权限
            else {
                if (AttachmentUtils.isUnSafe(file)) {
                    if (!file.delete()) {
                        LogKit.warn("file can not delete: {}", file.getAbsolutePath());
                    }
                    renderJson(Ret.fail().set("message", "不支持此类文件上传"));
                    return;
                }
            }
        }


        String mineType = uploadFile.getContentType();
        String fileType = mineType.split("/")[0];

        int maxImgSize = JPressOptions.getAsInt("attachment_img_maxsize", 10);
        int maxOtherSize = JPressOptions.getAsInt("attachment_other_maxsize", 100);

        Integer maxSize = "image".equals(fileType) ? maxImgSize : maxOtherSize;

        long fileSize = file.length() / 1024;
        if (maxSize > 0L && fileSize > maxSize * 1024) {
            if (!file.delete()) {
                LogKit.warn("file can not delete: {}", file.getAbsolutePath());
            }
            renderJson(Ret.fail().set("message", "上传文件大小不能超过 " + maxSize + " MB"));
            return;
        }

        String path = AttachmentManager.me().saveFile(uploadFile.getFile());

        File willUploadFile = AttachmentManager.me().getFile(path);
        AliyunOssUtils.upload(path, willUploadFile);

        //附件分类id
        Long categoryId = getParaToLong("categoryId");

        Attachment attachment = new Attachment();
        attachment.setCategoryId(categoryId);
        attachment.setUserId(getLoginedUser().getId());
        attachment.setTitle(uploadFile.getOriginalFileName());
        attachment.setPath(path.replace("\\", "/"));
        attachment.setSuffix(FileUtil.getSuffix(uploadFile.getFileName()));
        attachment.setMimeType(uploadFile.getContentType());

        Object attachmentId = service.save(attachment);

        //更新分类下的内容数量
        if (attachment.getCategoryId() != null) {
            categoryService.doUpdateAttachmentCategoryCount(attachment.getCategoryId().longValue());
        }

        boolean cropEnable = JPressOptions.getAsBool("attachment_img_crop_enable", false)
                && ImageUtils.isImageExtName(attachment.getPath());

        renderJson(Ret.ok().set("success", true)
                .set("src", attachment.getDomainPath())
                .set("path", attachment.getPath())
                .set("title", attachment.getTitle())
                .set("attachmentId", attachmentId)
                .set("cropEnable", cropEnable)
        );
    }


    @EmptyValidate({
            @Form(name = "path", message = "请先选择图片上传...")
    })
    public void doSaveImage(String path, Long attachmentId, float x, float y, float w, float h) {

        String contextPath = JFinal.me().getContextPath();
        if (StrUtil.isNotBlank(contextPath) && path.startsWith(contextPath)) {
            path = path.substring(contextPath.length());
        }

        File oldImageFile = AttachmentManager.me().getFile(path);
        File newImageFile = AttachmentManager.me().createNewFile(FileUtil.getSuffix(path));

        //进行剪切
        ImageUtils.crop(oldImageFile.getAbsolutePath(), newImageFile.getAbsolutePath(), (int) x, (int) y, (int) w, (int) h);

        // newImagePath 不带有 contextPath
        String newImagePath = AttachmentManager.me().saveFile(newImageFile);

        if (attachmentId != null) {
            Attachment attachment = service.findById(attachmentId);
            if (attachment != null) {
                attachment.setPath(newImagePath);
                service.update(attachment);

                if (!oldImageFile.delete()) {
                    LogKit.error("Can not delete file: " + oldImageFile);
                }
            }
        }

        renderJson(Ret.ok().set("success", true).set("src", JPressConfig.me.getAttachmentDomainOrContextPath() + newImagePath));
    }

}
